<h1 id="MyBatis-Plus"><a href="#MyBatis-Plus" class="headerlink" title="MyBatis-Plus"></a>MyBatis-Plus</h1><p><a href="https://baomidou.com/">官方文档</a></p>
<p><img src="MyBatis-Plus/1605316362346.png" alt="1605316362346"></p>
<p><strong>当前最新版本</strong></p>
<pre><code class="xml">&lt;dependency&gt;
    &lt;groupId&gt;com.baomidou&lt;/groupId&gt;
    &lt;artifactId&gt;mybatis-plus&lt;/artifactId&gt;
    &lt;version&gt;3.4.1&lt;/version&gt;
&lt;/dependency&gt;</code></pre>
<p><img src="MyBatis-Plus/1605316511521.png" alt="1605316511521"></p>
<h2 id="特性"><a href="#特性" class="headerlink" title="特性"></a>特性</h2><ul>
<li><strong>无侵入</strong>：只做增强不做改变，引入它不会对现有工程产生影响，如丝般顺滑</li>
<li><strong>损耗小</strong>：启动即会自动注入基本 CURD，性能基本无损耗，直接面向对象操作</li>
<li><strong>强大的 CRUD 操作</strong>：内置通用 Mapper、通用 Service，仅仅通过少量配置即可实现单表大部分 CRUD 操作，更有强大的条件构造器，满足各类使用需求</li>
<li><strong>支持 Lambda 形式调用</strong>：通过 Lambda 表达式，方便的编写各类查询条件，无需再担心字段写错</li>
<li><strong>支持主键自动生成</strong>：支持多达 4 种主键策略（内含分布式唯一 ID 生成器 - Sequence），可自由配置，完美解决主键问题</li>
<li><strong>支持 ActiveRecord 模式</strong>：支持 ActiveRecord 形式调用，实体类只需继承 Model 类即可进行强大的 CRUD 操作</li>
<li><strong>支持自定义全局通用操作</strong>：支持全局通用方法注入（ Write once, use anywhere ）</li>
<li><strong>内置代码生成器</strong>：采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码，支持模板引擎，更有超多自定义配置等您来使用</li>
<li><strong>内置分页插件</strong>：基于 MyBatis 物理分页，开发者无需关心具体操作，配置好插件之后，写分页等同于普通 List 查询</li>
<li><strong>分页插件支持多种数据库</strong>：支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库</li>
<li><strong>内置性能分析插件</strong>：可输出 Sql 语句以及其执行时间，建议开发测试时启用该功能，能快速揪出慢查询</li>
<li><strong>内置全局拦截插件</strong>：提供全表 delete 、 update 操作智能分析阻断，也可自定义拦截规则，预防误操作</li>
</ul>
<h2 id="快速开始"><a href="#快速开始" class="headerlink" title="快速开始"></a>快速开始</h2><p>我们将通过一个简单的 Demo 来阐述 MyBatis-Plus 的强大功能，在此之前，我们假设您已经：</p>
<ul>
<li>拥有 Java 开发环境以及相应 IDE</li>
<li>熟悉 Spring Boot</li>
<li>熟悉 Maven</li>
</ul>
<p>现有一张 <code>User</code> 表，其表结构如下：</p>
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>age</th>
<th>email</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>Jone</td>
<td>18</td>
<td><a href="mailto:&#x74;&#101;&#x73;&#116;&#x31;&#64;&#x62;&#x61;&#x6f;&#109;&#105;&#x64;&#111;&#x75;&#x2e;&#x63;&#x6f;&#109;">&#x74;&#101;&#x73;&#116;&#x31;&#64;&#x62;&#x61;&#x6f;&#109;&#105;&#x64;&#111;&#x75;&#x2e;&#x63;&#x6f;&#109;</a></td>
</tr>
<tr>
<td>2</td>
<td>Jack</td>
<td>20</td>
<td><a href="mailto:&#116;&#x65;&#x73;&#116;&#50;&#64;&#98;&#97;&#111;&#109;&#x69;&#x64;&#111;&#x75;&#46;&#x63;&#x6f;&#109;">&#116;&#x65;&#x73;&#116;&#50;&#64;&#98;&#97;&#111;&#109;&#x69;&#x64;&#111;&#x75;&#46;&#x63;&#x6f;&#109;</a></td>
</tr>
<tr>
<td>3</td>
<td>Tom</td>
<td>28</td>
<td><a href="mailto:&#x74;&#101;&#115;&#x74;&#51;&#x40;&#98;&#x61;&#x6f;&#109;&#x69;&#x64;&#x6f;&#117;&#x2e;&#99;&#x6f;&#x6d;">&#x74;&#101;&#115;&#x74;&#51;&#x40;&#98;&#x61;&#x6f;&#109;&#x69;&#x64;&#x6f;&#117;&#x2e;&#99;&#x6f;&#x6d;</a></td>
</tr>
<tr>
<td>4</td>
<td>Sandy</td>
<td>21</td>
<td><a href="mailto:&#x74;&#x65;&#x73;&#x74;&#x34;&#64;&#x62;&#97;&#x6f;&#x6d;&#105;&#100;&#x6f;&#x75;&#46;&#x63;&#x6f;&#109;">&#x74;&#x65;&#x73;&#x74;&#x34;&#64;&#x62;&#97;&#x6f;&#x6d;&#105;&#100;&#x6f;&#x75;&#46;&#x63;&#x6f;&#109;</a></td>
</tr>
<tr>
<td>5</td>
<td>Billie</td>
<td>24</td>
<td><a href="mailto:&#x74;&#x65;&#115;&#116;&#53;&#x40;&#x62;&#x61;&#111;&#x6d;&#105;&#100;&#x6f;&#x75;&#x2e;&#x63;&#x6f;&#x6d;">&#x74;&#x65;&#115;&#116;&#53;&#x40;&#x62;&#x61;&#111;&#x6d;&#105;&#100;&#x6f;&#x75;&#x2e;&#x63;&#x6f;&#x6d;</a></td>
</tr>
</tbody></table>
<p>其对应的数据库 Schema 脚本如下：</p>
<pre><code class="sql">DROP TABLE IF EXISTS user;

CREATE TABLE user
(
    id BIGINT(20) NOT NULL COMMENT &#39;主键ID&#39;,
    name VARCHAR(30) NULL DEFAULT NULL COMMENT &#39;姓名&#39;,
    age INT(11) NULL DEFAULT NULL COMMENT &#39;年龄&#39;,
    email VARCHAR(50) NULL DEFAULT NULL COMMENT &#39;邮箱&#39;,
    PRIMARY KEY (id)
);</code></pre>
<p>其对应的数据库 Data 脚本如下：</p>
<pre><code class="sql">DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, &#39;Jone&#39;, 18, &#39;test1@baomidou.com&#39;),
(2, &#39;Jack&#39;, 20, &#39;test2@baomidou.com&#39;),
(3, &#39;Tom&#39;, 28, &#39;test3@baomidou.com&#39;),
(4, &#39;Sandy&#39;, 21, &#39;test4@baomidou.com&#39;),
(5, &#39;Billie&#39;, 24, &#39;test5@baomidou.com&#39;);</code></pre>
<h3 id="初始化项目"><a href="#初始化项目" class="headerlink" title="初始化项目"></a>初始化项目</h3><p><img src="MyBatis-Plus/1605316822767.png" alt="1605316822767"></p>
<p><img src="MyBatis-Plus/1605316855472.png" alt="1605316855472"></p>
<p><img src="MyBatis-Plus/1605316892744.png" alt="1605316892744"></p>
<p><strong>添加依赖:</strong></p>
<pre><code class="xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
         xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
    &lt;parent&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
        &lt;version&gt;2.4.0&lt;/version&gt;
        &lt;relativePath/&gt; &lt;!-- lookup parent from repository --&gt;
    &lt;/parent&gt;
    &lt;groupId&gt;com.changan&lt;/groupId&gt;
    &lt;artifactId&gt;springboot-mp&lt;/artifactId&gt;
    &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
    &lt;name&gt;springboot-mp&lt;/name&gt;
    &lt;description&gt;Demo project for Spring Boot&lt;/description&gt;

    &lt;properties&gt;
        &lt;java.version&gt;1.8&lt;/java.version&gt;
    &lt;/properties&gt;

    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
        &lt;/dependency&gt;

        &lt;dependency&gt;
            &lt;groupId&gt;mysql&lt;/groupId&gt;
            &lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;
            &lt;version&gt;8.0.13&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
            &lt;artifactId&gt;lombok&lt;/artifactId&gt;
            &lt;optional&gt;true&lt;/optional&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
            &lt;scope&gt;test&lt;/scope&gt;
        &lt;/dependency&gt;

        &lt;dependency&gt;
            &lt;groupId&gt;com.baomidou&lt;/groupId&gt;
            &lt;artifactId&gt;mybatis-plus-boot-starter&lt;/artifactId&gt;
            &lt;version&gt;3.4.1&lt;/version&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;

    &lt;build&gt;
        &lt;plugins&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;

&lt;/project&gt;</code></pre>
<p><strong>项目配置:</strong></p>
<pre><code class="yaml">#项目名称
spring:
  application:
    name: springboot-mp
  #数据源配置
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis?characterEncoding=UTF-8&amp;useUnicode=true&amp;serverTimezone=GMT%2B8
    username: root
    password: root

#项目端口
server:
  port: 8080</code></pre>
<p>在 Spring Boot 启动类中添加 <code>@MapperScan</code> 注解，扫描 Mapper 文件夹：</p>
<p><img src="MyBatis-Plus/1605317404210.png" alt="1605317404210"></p>
<p><strong>编码:</strong></p>
<p>编写实体类 <code>User.java</code>（此处使用了 <a href="https://www.projectlombok.org/">Lombok</a><a href="https://www.projectlombok.org/"> </a> 简化代码）,记得安装Lombok的插件</p>
<pre><code class="java">@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}</code></pre>
<p>编写Mapper类 <code>UserMapper.java</code></p>
<pre><code class="java">/**
 * @author NieChangan
 */
public interface UserMapper extends BaseMapper&lt;User&gt; {

}</code></pre>
<h2 id="基本的CURD操作"><a href="#基本的CURD操作" class="headerlink" title="基本的CURD操作"></a>基本的CURD操作</h2><h3 id="配置SQL日志打印"><a href="#配置SQL日志打印" class="headerlink" title="配置SQL日志打印"></a>配置SQL日志打印</h3><pre><code class="yaml">mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl</code></pre>
<h3 id="增加操作"><a href="#增加操作" class="headerlink" title="增加操作"></a>增加操作</h3><pre><code class="java">/**
     * 当自己添加ID的时候,会根据输入的ID值进行插入
     * 如果没有设置ID则会自动填充一个ID
     */
@Test
void addUser() {
    User user = new User();
    //user.setId(10l);
    user.setName(&quot;老赵&quot;);
    user.setAge(20);
    user.setEmail(&quot;123@qq.com&quot;);
    userMapper.insert(user);
}</code></pre>
<h3 id="修改操作"><a href="#修改操作" class="headerlink" title="修改操作"></a>修改操作</h3><pre><code class="java">@Test
void updateUser() {
    User user = new User();
    user.setId(10l);
    user.setName(&quot;班长&quot;);
    user.setAge(22);
    user.setEmail(&quot;666@qq.com&quot;);
    userMapper.updateById(user);
}</code></pre>
<h3 id="删除操作"><a href="#删除操作" class="headerlink" title="删除操作"></a>删除操作</h3><pre><code class="java">/**
     * 根据ID进行删除
     */
@Test
public void deleteUser(){
    int i = userMapper.deleteById(1327425146843054082l);
    System.out.println(i);
}

/**
     * 根据Wrapper进行删除
     */
@Test
public void deleteUser1(){
    QueryWrapper&lt;User&gt; wrapper = new QueryWrapper&lt;User&gt;();
    wrapper.likeRight(&quot;name&quot;,&quot;J&quot;);
    int delete = userMapper.delete(wrapper);
    System.out.println(delete);
}

/**
     * 根据Map进行删除
     */
@Test
public void deleteUser2(){
    Map&lt;String,Object&gt; map = new HashMap&lt;&gt;();
    map.put(&quot;name&quot;,&quot;老赵&quot;);
    int delete = userMapper.deleteByMap(map);
    System.out.println(delete);
}

/**
     * 批量删除
     */
@Test
public void deleteUser3(){
    int delete = userMapper.deleteBatchIds(Arrays.asList(1l,3l,4l,5l));
    System.out.println(delete);
}</code></pre>
<h3 id="查询操作"><a href="#查询操作" class="headerlink" title="查询操作"></a>查询操作</h3><pre><code class="java">/**
 * 通过ID进行查询
 */
@Test
public void findById(){
    User user = userMapper.selectById(1l);
    System.out.println(user.toString());
}

/**
 * 使用Wrapper进行高级查询
 */
@Test
public void find2(){
    QueryWrapper&lt;User&gt; wrapper = new QueryWrapper&lt;&gt;();
    wrapper.ge(&quot;age&quot;,20);
    wrapper.likeRight(&quot;name&quot;,&quot;J&quot;);
    List&lt;User&gt; users = userMapper.selectList(wrapper);
    users.forEach(user -&gt; {
        System.out.println(user.toString());
    });
}

/**
 * 使用Wrapper进行高级查询
 */
@Test
public void find3(){
    QueryWrapper&lt;User&gt; wrapper = new QueryWrapper&lt;&gt;();
    wrapper.between(&quot;age&quot;,18,22);
    List&lt;User&gt; users = userMapper.selectList(wrapper);
    users.forEach(user -&gt; {
        System.out.println(user.toString());
    });
}

/**
 * 退可使用mybatis的原生查询
 */
@Test
public void find4(){
    List&lt;User&gt; users = userMapper.selectLikeName(&quot;J&quot;);
    users.forEach(user -&gt; {
        System.out.println(user.toString());
    });
}

/**
 * 批量查询
 */
@Test
public void find5(){
    List&lt;User&gt; users = userMapper.selectBatchIds(Arrays.asList(1l,3l,4l,5l));
    users.forEach(user -&gt; {
        System.out.println(user.toString());
    });
}

/**
 * 统计数量
 */
@Test
public void find6(){
    Integer count = userMapper.selectCount(null);
    System.out.println(count);
}

/**
 * 根据Map查询
 */
@Test
public void find7(){
    Map&lt;String,Object&gt; map = new HashMap&lt;&gt;();
    map.put(&quot;name&quot;,&quot;Billie&quot;);
    List&lt;User&gt; users = userMapper.selectByMap(map);
    users.forEach(user -&gt; {
        System.out.println(user.toString());
    });
}

/**
 * 查询所有
 */
@Test
public void findByAll(){
    List&lt;User&gt; users = userMapper.selectList(null);
    for (User user : users) {
        System.out.println(user.toString());
    }
}</code></pre>
<h2 id="高级用法"><a href="#高级用法" class="headerlink" title="高级用法"></a>高级用法</h2><h3 id="注解"><a href="#注解" class="headerlink" title="注解"></a>注解</h3><p><strong>@TableName</strong></p>
<ul>
<li>描述：表名注解</li>
</ul>
<table>
<thead>
<tr>
<th>属性</th>
<th>类型</th>
<th>必须指定</th>
<th>默认值</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>value</td>
<td>String</td>
<td>否</td>
<td>“”</td>
<td>表名</td>
</tr>
<tr>
<td>schema</td>
<td>String</td>
<td>否</td>
<td>“”</td>
<td>schema</td>
</tr>
<tr>
<td>keepGlobalPrefix</td>
<td>boolean</td>
<td>否</td>
<td>false</td>
<td>是否保持使用全局的 tablePrefix 的值(如果设置了全局 tablePrefix 且自行设置了 value 的值)</td>
</tr>
<tr>
<td>resultMap</td>
<td>String</td>
<td>否</td>
<td>“”</td>
<td>xml 中 resultMap 的 id</td>
</tr>
<tr>
<td>autoResultMap</td>
<td>boolean</td>
<td>否</td>
<td>false</td>
<td>是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建并注入)</td>
</tr>
</tbody></table>
<p><strong>@TableId</strong></p>
<p>注解</p>
<blockquote>
<p>介绍 <code>MybatisPlus</code> 注解包相关类详解(更多详细描述可点击查看源码注释)</p>
</blockquote>
<ul>
<li>描述：表名注解</li>
</ul>
<table>
<thead>
<tr>
<th>属性</th>
<th>类型</th>
<th>必须指定</th>
<th>默认值</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>value</td>
<td>String</td>
<td>否</td>
<td>“”</td>
<td>表名</td>
</tr>
<tr>
<td>schema</td>
<td>String</td>
<td>否</td>
<td>“”</td>
<td>schema</td>
</tr>
<tr>
<td>keepGlobalPrefix</td>
<td>boolean</td>
<td>否</td>
<td>false</td>
<td>是否保持使用全局的 tablePrefix 的值(如果设置了全局 tablePrefix 且自行设置了 value 的值)</td>
</tr>
<tr>
<td>resultMap</td>
<td>String</td>
<td>否</td>
<td>“”</td>
<td>xml 中 resultMap 的 id</td>
</tr>
<tr>
<td>autoResultMap</td>
<td>boolean</td>
<td>否</td>
<td>false</td>
<td>是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建并注入)</td>
</tr>
</tbody></table>
<p>关于<code>autoResultMap</code>的说明:</p>
<p>mp会自动构建一个<code>ResultMap</code>并注入到mybatis里(一般用不上).下面讲两句: 因为mp底层是mybatis,所以一些mybatis的常识你要知道,mp只是帮你注入了常用crud到mybatis里 注入之前可以说是动态的(根据你entity的字段以及注解变化而变化),但是注入之后是静态的(等于你写在xml的东西) 而对于直接指定<code>typeHandler</code>,mybatis只支持你写在2个地方:</p>
<ol>
<li>定义在resultMap里,只作用于select查询的返回结果封装</li>
<li>定义在<code>insert</code>和<code>update</code>sql的<code>#{property}</code>里的<code>property</code>后面(例:<code>#{property,typehandler=xxx.xxx.xxx}</code>),只作用于<code>设置值</code> 而除了这两种直接指定<code>typeHandler</code>,mybatis有一个全局的扫描你自己的<code>typeHandler</code>包的配置,这是根据你的<code>property</code>的类型去找<code>typeHandler</code>并使用.</li>
</ol>
<p><strong>@TableId</strong></p>
<ul>
<li>描述：主键注解</li>
</ul>
<table>
<thead>
<tr>
<th>属性</th>
<th>类型</th>
<th>必须指定</th>
<th>默认值</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>value</td>
<td>String</td>
<td>否</td>
<td>“”</td>
<td>主键字段名</td>
</tr>
<tr>
<td>type</td>
<td>Enum</td>
<td>否</td>
<td>IdType.NONE</td>
<td>主键类型</td>
</tr>
</tbody></table>
<p><strong>IdType</strong></p>
<table>
<thead>
<tr>
<th>值</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>AUTO</td>
<td>数据库ID自增</td>
</tr>
<tr>
<td>NONE</td>
<td>无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)</td>
</tr>
<tr>
<td>INPUT</td>
<td>insert前自行set主键值</td>
</tr>
<tr>
<td>ASSIGN_ID</td>
<td>分配ID(主键类型为Number(Long和Integer)或String)(since 3.3.0),使用接口<code>IdentifierGenerator</code>的方法<code>nextId</code>(默认实现类为<code>DefaultIdentifierGenerator</code>雪花算法)</td>
</tr>
<tr>
<td>ASSIGN_UUID</td>
<td>分配UUID,主键类型为String(since 3.3.0),使用接口<code>IdentifierGenerator</code>的方法<code>nextUUID</code>(默认default方法)</td>
</tr>
<tr>
<td>ID_WORKER</td>
<td>分布式全局唯一ID 长整型类型(please use <code>ASSIGN_ID</code>)</td>
</tr>
<tr>
<td>UUID</td>
<td>32位UUID字符串(please use <code>ASSIGN_UUID</code>)</td>
</tr>
<tr>
<td>ID_WORKER_STR</td>
<td>分布式全局唯一ID 字符串类型(please use <code>ASSIGN_ID</code>)</td>
</tr>
</tbody></table>
<p><strong>@TableField</strong></p>
<p><strong>@TableName</strong></p>
<ul>
<li>描述：表名注解</li>
</ul>
<table>
<thead>
<tr>
<th>属性</th>
<th>类型</th>
<th>必须指定</th>
<th>默认值</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>value</td>
<td>String</td>
<td>否</td>
<td>“”</td>
<td>表名</td>
</tr>
<tr>
<td>schema</td>
<td>String</td>
<td>否</td>
<td>“”</td>
<td>schema</td>
</tr>
<tr>
<td>keepGlobalPrefix</td>
<td>boolean</td>
<td>否</td>
<td>false</td>
<td>是否保持使用全局的 tablePrefix 的值(如果设置了全局 tablePrefix 且自行设置了 value 的值)</td>
</tr>
<tr>
<td>resultMap</td>
<td>String</td>
<td>否</td>
<td>“”</td>
<td>xml 中 resultMap 的 id</td>
</tr>
<tr>
<td>autoResultMap</td>
<td>boolean</td>
<td>否</td>
<td>false</td>
<td>是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建并注入)</td>
</tr>
</tbody></table>
<p>关于<code>autoResultMap</code>的说明:</p>
<p>mp会自动构建一个<code>ResultMap</code>并注入到mybatis里(一般用不上).下面讲两句: 因为mp底层是mybatis,所以一些mybatis的常识你要知道,mp只是帮你注入了常用crud到mybatis里 注入之前可以说是动态的(根据你entity的字段以及注解变化而变化),但是注入之后是静态的(等于你写在xml的东西) 而对于直接指定<code>typeHandler</code>,mybatis只支持你写在2个地方:</p>
<ol>
<li>定义在resultMap里,只作用于select查询的返回结果封装</li>
<li>定义在<code>insert</code>和<code>update</code>sql的<code>#{property}</code>里的<code>property</code>后面(例:<code>#{property,typehandler=xxx.xxx.xxx}</code>),只作用于<code>设置值</code> 而除了这两种直接指定<code>typeHandler</code>,mybatis有一个全局的扫描你自己的<code>typeHandler</code>包的配置,这是根据你的<code>property</code>的类型去找<code>typeHandler</code>并使用.</li>
</ol>
<p><strong>@TableId</strong></p>
<ul>
<li>描述：主键注解</li>
</ul>
<table>
<thead>
<tr>
<th>属性</th>
<th>类型</th>
<th>必须指定</th>
<th>默认值</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>value</td>
<td>String</td>
<td>否</td>
<td>“”</td>
<td>主键字段名</td>
</tr>
<tr>
<td>type</td>
<td>Enum</td>
<td>否</td>
<td>IdType.NONE</td>
<td>主键类型</td>
</tr>
</tbody></table>
<p><strong>IdType</strong></p>
<table>
<thead>
<tr>
<th>值</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>AUTO</td>
<td>数据库ID自增</td>
</tr>
<tr>
<td>NONE</td>
<td>无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)</td>
</tr>
<tr>
<td>INPUT</td>
<td>insert前自行set主键值</td>
</tr>
<tr>
<td>ASSIGN_ID</td>
<td>分配ID(主键类型为Number(Long和Integer)或String)(since 3.3.0),使用接口<code>IdentifierGenerator</code>的方法<code>nextId</code>(默认实现类为<code>DefaultIdentifierGenerator</code>雪花算法)</td>
</tr>
<tr>
<td>ASSIGN_UUID</td>
<td>分配UUID,主键类型为String(since 3.3.0),使用接口<code>IdentifierGenerator</code>的方法<code>nextUUID</code>(默认default方法)</td>
</tr>
<tr>
<td>ID_WORKER</td>
<td>分布式全局唯一ID 长整型类型(please use <code>ASSIGN_ID</code>)</td>
</tr>
<tr>
<td>UUID</td>
<td>32位UUID字符串(please use <code>ASSIGN_UUID</code>)</td>
</tr>
<tr>
<td>ID_WORKER_STR</td>
<td>分布式全局唯一ID 字符串类型(please use <code>ASSIGN_ID</code>)</td>
</tr>
</tbody></table>
<p><strong>@TableField</strong></p>
<ul>
<li>描述：字段注解(非主键)</li>
</ul>
<table>
<thead>
<tr>
<th>属性</th>
<th>类型</th>
<th>必须指定</th>
<th>默认值</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>value</td>
<td>String</td>
<td>否</td>
<td>“”</td>
<td>数据库字段名</td>
</tr>
<tr>
<td>el</td>
<td>String</td>
<td>否</td>
<td>“”</td>
<td>映射为原生 <code>#{ ... }</code> 逻辑,相当于写在 xml 里的 <code>#{ ... }</code> 部分</td>
</tr>
<tr>
<td>exist</td>
<td>boolean</td>
<td>否</td>
<td>true</td>
<td>是否为数据库表字段</td>
</tr>
<tr>
<td>condition</td>
<td>String</td>
<td>否</td>
<td>“”</td>
<td>字段 <code>where</code> 实体查询比较条件,有值设置则按设置的值为准,没有则为默认全局的 <code>%s=#{%s}</code>,<a href="https://github.com/baomidou/mybatis-plus/blob/3.0/mybatis-plus-annotation/src/main/java/com/baomidou/mybatisplus/annotation/SqlCondition.java">参考</a></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td>update</td>
<td>String</td>
<td>否</td>
<td>“”</td>
<td>字段 <code>update set</code> 部分注入, 例如：update=”%s+1”：表示更新时会set version=version+1(该属性优先级高于 <code>el</code> 属性)</td>
</tr>
<tr>
<td>insertStrategy</td>
<td>Enum</td>
<td>N</td>
<td>DEFAULT</td>
<td>举例：NOT_NULL: <code>insert  into table_a(&lt;if test=&quot;columnProperty != null&quot;&gt;column&lt;/if&gt;)  values (&lt;if test=&quot;columnProperty !=  null&quot;&gt;#{columnProperty}&lt;/if&gt;)</code></td>
</tr>
<tr>
<td>updateStrategy</td>
<td>Enum</td>
<td>N</td>
<td>DEFAULT</td>
<td>举例：IGNORED: <code>update table_a set column=#{columnProperty}</code></td>
</tr>
<tr>
<td>whereStrategy</td>
<td>Enum</td>
<td>N</td>
<td>DEFAULT</td>
<td>举例：NOT_EMPTY: <code>where &lt;if test=&quot;columnProperty != null and columnProperty!=&#39;&#39;&quot;&gt;column=#{columnProperty}&lt;/if&gt;</code></td>
</tr>
<tr>
<td>fill</td>
<td>Enum</td>
<td>否</td>
<td>FieldFill.DEFAULT</td>
<td>字段自动填充策略</td>
</tr>
<tr>
<td>select</td>
<td>boolean</td>
<td>否</td>
<td>true</td>
<td>是否进行 select 查询</td>
</tr>
<tr>
<td>keepGlobalFormat</td>
<td>boolean</td>
<td>否</td>
<td>false</td>
<td>是否保持使用全局的 format 进行处理</td>
</tr>
<tr>
<td>jdbcType</td>
<td>JdbcType</td>
<td>否</td>
<td>JdbcType.UNDEFINED</td>
<td>JDBC类型 (该默认值不代表会按照该值生效)</td>
</tr>
<tr>
<td>typeHandler</td>
<td>Class&lt;? extends TypeHandler&gt;</td>
<td>否</td>
<td>UnknownTypeHandler.class</td>
<td>类型处理器 (该默认值不代表会按照该值生效)</td>
</tr>
<tr>
<td>numericScale</td>
<td>String</td>
<td>否</td>
<td>“”</td>
<td>指定小数点后保留的位数</td>
</tr>
</tbody></table>
<h3 id="分页查询"><a href="#分页查询" class="headerlink" title="分页查询"></a>分页查询</h3><p><strong>分页插件</strong></p>
<pre><code class="xml">&lt;!-- spring xml 方式 --&gt;
&lt;property name=&quot;plugins&quot;&gt;
    &lt;array&gt;
        &lt;bean class=&quot;com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor&quot;&gt;
            &lt;property name=&quot;sqlParser&quot; ref=&quot;自定义解析类、可以没有&quot;/&gt;
            &lt;property name=&quot;dialectClazz&quot; value=&quot;自定义方言类、可以没有&quot;/&gt;
            &lt;!-- COUNT SQL 解析.可以没有 --&gt;
            &lt;property name=&quot;countSqlParser&quot; ref=&quot;countSqlParser&quot;/&gt;
        &lt;/bean&gt;
    &lt;/array&gt;
&lt;/property&gt;

&lt;bean id=&quot;countSqlParser&quot; class=&quot;com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize&quot;&gt;
    &lt;!-- 设置为 true 可以优化部分 left join 的sql --&gt;
    &lt;property name=&quot;optimizeJoin&quot; value=&quot;true&quot;/&gt;
&lt;/bean&gt;</code></pre>
<pre><code class="java">//Spring boot方式
@Configuration
@MapperScan(&quot;com.baomidou.cloud.service.*.mapper*&quot;)
public class MybatisPlusConfig {

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作， true调回到首页，false 继续请求  默认false
        // paginationInterceptor.setOverflow(false);
        // 设置最大单页限制数量，默认 500 条，-1 不受限制
        // paginationInterceptor.setLimit(500);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }
}</code></pre>
<pre><code class="java">/**
 * 分页查询
 */
@Test
public void findByPage(){
    Page&lt;User&gt; page = new Page&lt;&gt;(1,3);
    QueryWrapper&lt;User&gt; wrapper = new QueryWrapper&lt;&gt;();
    wrapper.ge(&quot;age&quot;,20);
    Page&lt;User&gt; page1 = userMapper.selectPage(page,wrapper);
    for (User user : page1.getRecords()) {
        System.out.println(user.toString());
    }
}</code></pre>
